package com.greensam.pixelengine.facade.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.json.JSONUtil;
import com.greensam.pixelengine.exception.BusinessException;
import com.greensam.pixelengine.exception.ResultCode;
import com.greensam.pixelengine.exception.ThrowUtils;
import com.greensam.pixelengine.facade.SpaceAnalyzeFacadeService;
import com.greensam.pixelengine.pojo.emuns.ErrorCodeEnum;
import com.greensam.pixelengine.pojo.emuns.PictureSizeEnum;
import com.greensam.pixelengine.pojo.emuns.TimeDimensionEnum;
import com.greensam.pixelengine.pojo.entity.PicturePo;
import com.greensam.pixelengine.pojo.entity.SpacePo;
import com.greensam.pixelengine.pojo.query.SpaceRankListQuery;
import com.greensam.pixelengine.pojo.vo.space.request.*;
import com.greensam.pixelengine.pojo.vo.space.response.*;
import com.greensam.pixelengine.service.PictureDataService;
import com.greensam.pixelengine.service.RoleDataService;
import com.greensam.pixelengine.service.SpaceDataService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.WeekFields;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Ma Chengrui
 * @since 2025/9/17 15:50
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SpaceAnalyzeFacadeServiceImpl implements SpaceAnalyzeFacadeService {

    private final RoleDataService roleDataService;
    private final PictureDataService pictureDataService;
    private final SpaceDataService spaceDataService;

    @Override
    public SpaceUsageAnalyzeVo getSpaceUsageAnalyze(SpaceUsageAnalyzeRequest request, Long userId) {
        // 校验权限
        checkSpaceAnalyzeAuth(request, userId);
        if (request.getIsQueryAll()) {
            // 全空间分析
            return buildSpaceUsageAnalyzeVo(Boolean.FALSE);
        } else if (request.getIsQueryPublic()) {
            // 公共图库分析
            return buildSpaceUsageAnalyzeVo(Boolean.TRUE);
        } else {
            // 私人图库空间分析
            Long spaceId = request.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCodeEnum.ParamValidError, "空间ID不能为空");
            SpacePo spacePo = spaceDataService.getSpaceById(spaceId)
                    .orElseThrow(() -> new BusinessException(ErrorCodeEnum.SpaceNotExist, "空间不存在"));
            SpaceUsageAnalyzeVo analyzeVo = BeanUtil.copyProperties(spacePo, SpaceUsageAnalyzeVo.class);
            // 计算空间使用比例
            Long totalSize = spacePo.getTotalSize() != null ? spacePo.getTotalSize() : Long.valueOf(0L);
            Long maxSize = spacePo.getMaxSize() != null ? spacePo.getMaxSize() : Long.valueOf(1L);
            Double sizeUsageRatio = NumberUtil.round(totalSize * 100.0 / maxSize, 2).doubleValue();
            analyzeVo.setSizeUsageRatio(sizeUsageRatio);
            return analyzeVo;
        }
    }

    /**
     * 构建 全空间/公共图库 资源使用
     *
     * @param isPublic 是否查询公共图库
     * @author Ma Chengrui
     * @since 2025/9/17
     */
    public SpaceUsageAnalyzeVo buildSpaceUsageAnalyzeVo(Boolean isPublic) {
        List<PicturePo> picturePos = pictureDataService.listPicture(null, isPublic);
        if (CollectionUtils.isEmpty(picturePos)) {
            return null;
        }
        LongSummaryStatistics stats = picturePos.stream()
                .filter(p -> p.getPicSize() != null)
                .collect(Collectors.summarizingLong(PicturePo::getPicSize));

        SpaceUsageAnalyzeVo analyzeVo = new SpaceUsageAnalyzeVo();
        analyzeVo.setTotalCount(stats.getCount());
        analyzeVo.setTotalSize(stats.getSum());
        analyzeVo.setMaxSize(null);
        analyzeVo.setSizeUsageRatio(null);
        return analyzeVo;
    }

    @Override
    public List<SpaceCategoryAnalyzeVo> listSpaceCategoryAnalyze(SpaceCategoryAnalyzeRequest request, Long userId) {
        // 校验权限
        checkSpaceAnalyzeAuth(request, userId);

        // 查询所有符合条件的图片
        List<PicturePo> picturePos;
        if (request.getIsQueryAll()) {
            picturePos = pictureDataService.listPicture(null, Boolean.FALSE);
        } else if (request.getIsQueryPublic()) {
            picturePos = pictureDataService.listPicture(null, Boolean.TRUE);
        } else {
            Long spaceId = request.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCodeEnum.ParamValidError, "空间ID不能为空");
            picturePos = pictureDataService.listPicture(spaceId, Boolean.FALSE);
        }
        if (CollectionUtils.isEmpty(picturePos)) {
            return Collections.emptyList();
        }

        // 分组
        Map<String, LongSummaryStatistics> categoryMap = picturePos.stream()
                .filter(picturePo -> picturePo.getCategory() != null && !picturePo.getCategory().isBlank())
                .collect(Collectors.groupingBy(PicturePo::getCategory,
                        Collectors.summarizingLong(p -> p.getPicSize() == null ? 0L : p.getPicSize())));

        // 构建返回结果
        return categoryMap.entrySet().stream()
                .map(entry -> {
                    SpaceCategoryAnalyzeVo vo = new SpaceCategoryAnalyzeVo();
                    vo.setCategory(entry.getKey());
                    vo.setCount(entry.getValue().getCount());
                    vo.setTotalSize(entry.getValue().getSum());
                    return vo;
                })
                .sorted(Comparator.comparingLong(SpaceCategoryAnalyzeVo::getCount).reversed())
                .toList();
    }

    @Override
    public List<SpaceTagAnalyzeVo> listSpaceTagAnalyze(SpaceTagAnalyzeRequest request, Long userId) {
        // 校验权限
        checkSpaceAnalyzeAuth(request, userId);

        // 查询所有符合条件的标签
        List<PicturePo> picturePos;
        if (request.getIsQueryAll()) {
            picturePos = pictureDataService.listPicture(null, Boolean.FALSE);
        } else if (request.getIsQueryPublic()) {
            picturePos = pictureDataService.listPicture(null, Boolean.TRUE);
        } else {
            Long spaceId = request.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCodeEnum.ParamValidError, "空间ID不能为空");
            picturePos = pictureDataService.listPicture(spaceId, Boolean.FALSE);
        }
        if (CollectionUtils.isEmpty(picturePos)) {
            return Collections.emptyList();
        }

        // 合并所有标签并统计使用次数
        Map<String, Long> tagCountMap = picturePos.stream()
                .filter(picturePo -> picturePo.getTags() != null && !picturePo.getTags().isBlank())
                .flatMap(picturePo -> JSONUtil.parseArray(picturePo.getTags()).toList(String.class).stream())
                .collect(Collectors.groupingBy(tag -> tag, Collectors.counting()));

        // 构建返回结果，按使用次数降序排序
        return tagCountMap.entrySet().stream()
                .map(entry -> {
                    SpaceTagAnalyzeVo vo = new SpaceTagAnalyzeVo();
                    vo.setTag(entry.getKey());
                    vo.setCount(entry.getValue());
                    return vo;
                })
                .sorted(Comparator.comparingLong(SpaceTagAnalyzeVo::getCount).reversed())
                .toList();
    }

    @Override
    public List<SpaceSizeAnalyzeVo> listSpaceSizeAnalyze(SpaceSizeAnalyzeRequest request, Long userId) {
        // 校验权限
        checkSpaceAnalyzeAuth(request, userId);

        // 查询所有符合条件的图片大小
        List<PicturePo> picturePos;
        if (request.getIsQueryAll()) {
            picturePos = pictureDataService.listPicture(null, Boolean.FALSE);
        } else if (request.getIsQueryPublic()) {
            picturePos = pictureDataService.listPicture(null, Boolean.TRUE);
        } else {
            Long spaceId = request.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCodeEnum.ParamValidError, "空间ID不能为空");
            picturePos = pictureDataService.listPicture(spaceId, Boolean.FALSE);
        }
        if (CollectionUtils.isEmpty(picturePos)) {
            return Collections.emptyList();
        }

        // 定义分段范围，注意使用有序Map
        Map<PictureSizeEnum, Long> countMap = picturePos.stream()
                .map(picturePo -> PictureSizeEnum.match(picturePo.getPicSize() == null ? 0L : picturePo.getPicSize()))
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        // 构建返回结果
        return Arrays.stream(PictureSizeEnum.values())
                .map(size -> {
                    SpaceSizeAnalyzeVo vo = new SpaceSizeAnalyzeVo();
                    vo.setSizeRange(size);
                    vo.setCount(countMap.getOrDefault(size, 0L));
                    return vo;
                })
                .toList();
    }

    @Override
    public List<SpaceUserAnalyzeVo> listSpaceUserAnalyze(SpaceUserAnalyzeRequest request) {
        // 校验参数
        checkSpaceAnalyzeAuth(request, request.getUserId());

        // 查询所有符合条件的图片
        List<PicturePo> picturePos;
        if (request.getIsQueryAll()) {
            picturePos = pictureDataService.listPicture(null, Boolean.FALSE);
        } else if (request.getIsQueryPublic()) {
            picturePos = pictureDataService.listPicture(null, Boolean.TRUE);
        } else {
            Long spaceId = request.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCodeEnum.ParamValidError, "空间ID不能为空");
            picturePos = pictureDataService.listPicture(spaceId, Boolean.FALSE);
        }
        if (CollectionUtils.isEmpty(picturePos)) {
            return Collections.emptyList();
        }
        // 分析维度：day / week / month / year
        DateTimeFormatter dayFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter monthFormatter = DateTimeFormatter.ofPattern("yyyy-MM");
        DateTimeFormatter yearFormatter = DateTimeFormatter.ofPattern("yyyy");

        TimeDimensionEnum dim = request.getTimeDimension();
        // 分组排序
        Map<String, Long> periodCountMap = picturePos.stream()
                .filter(picturePo -> picturePo.getCreateBy().equals(request.getUserId()))
                .collect(Collectors.groupingBy(picturePo -> {
                    LocalDateTime createTime = picturePo.getCreateTime();
                    return switch (dim) {
                        case DAY -> createTime.format(dayFormatter);
                        case WEEK -> {
                            WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 4);
                            int week = createTime.get(weekFields.weekOfWeekBasedYear());
                            yield createTime.getYear() + "-W" + week;
                        }
                        case MONTH -> createTime.format(monthFormatter);
                        case YEAR -> createTime.format(yearFormatter);
                        default -> throw new BusinessException(ErrorCodeEnum.ParamValidError, "时间维度错误");
                    };
                }, Collectors.counting()));

        // 构建返回结果

        return periodCountMap.entrySet().stream()
                .map(entry -> {
                    SpaceUserAnalyzeVo vo = new SpaceUserAnalyzeVo();
                    vo.setPeriod(entry.getKey());
                    vo.setCount(entry.getValue());
                    return vo;
                })
                .toList();
    }

    @Override
    public List<SpaceVo> listSpaceRankAnalyze(SpaceRankAnalyzeRequest request, Long userId) {
        // 校验参数
        ThrowUtils.throwIf(!roleDataService.isAdmin(userId), ResultCode.NO_AUTH_ERROR, "操作无权限");
        // 查询所有符合条件的空间
        SpaceRankListQuery query = BeanUtil.copyProperties(request, SpaceRankListQuery.class);
        List<SpacePo> spacePos = spaceDataService.listSpaceRank(query);
        if (CollectionUtils.isEmpty(spacePos)) {
            return Collections.emptyList();
        }
        // 构建返回结果
        return spacePos.stream()
                .map(SpaceVo::spacePo2Vo)
                .toList();
    }

    public void checkSpaceAnalyzeAuth(SpaceAnalyzeRequest request, Long userId) {
        if (request.getIsQueryAll() || request.getIsQueryPublic()) {
            // 全空间分析或公共图库分析仅管理员
            ThrowUtils.throwIf(!roleDataService.isAdmin(userId), ResultCode.NO_AUTH_ERROR, "操作无权限");
        } else {
            Long spaceId = request.getSpaceId();
            ThrowUtils.throwIf(spaceId == null, ErrorCodeEnum.ParamValidError, "空间ID不能为空");
            SpacePo spacePo = spaceDataService.getSpaceById(spaceId)
                    .orElseThrow(() -> new BusinessException(ErrorCodeEnum.SpaceNotExist, "空间不存在"));
            ThrowUtils.throwIf(!roleDataService.isAdmin(userId) && !spacePo.getCreateBy().equals(userId), ResultCode.NO_AUTH_ERROR, "没有该空间权限");
        }
    }
}
